#include "GameOfLife.h"
#include "SDL.h"
#include <random>

void GameOfLife::init()
{
	App::init();
	world.renderer = mRenderer;
	//random();
	event_tables[EVENT_MOUSE].push_back((event_handler)&GameOfLife::onClick);
	event_tables[EVENT_KEY].push_back((event_handler)&GameOfLife::onKeyEvent);
}

void GameOfLife::tick()
{
	SDL_SetRenderDrawColor(mRenderer, 0, 0, 0, 0);
	SDL_RenderClear(mRenderer);
	
	world.draw();
	if (count > 0) 
	{
		--count;
	}
	else 
	{
		count = 20;
		if (start)
			simulation();
	}

	SDL_RenderPresent(mRenderer);
}

void GameOfLife::random()
{
	std::default_random_engine e;
	std::bernoulli_distribution u(.3);
	for (Bitmap& row : world.blocks[world.currBlocks])
	{
		for (int i = 0; i < 40; ++i)
		{
			row[i] = u(e);
		}
	}
}

void GameOfLife::simulation()
{
	int cellsAround = 0;
	int nxt = (world.currBlocks + 1) % 2;
	for (int y = 0; y < world.height; y++)
	{
		for (int x = 0; x < world.width; x++)
		{
			cellsAround = getCellAround(x, y);
			if (world.blocks[world.currBlocks][y][x])
			{
				if (cellsAround < 2 || cellsAround > 3) 
				{
					world.blocks[nxt][y][x] = false;
				}
				else 
				{
					world.blocks[nxt][y][x] = true;
				}
			} 
			else
			{
				if (cellsAround == 3)
				{
					world.blocks[nxt][y][x] = true;
				}
				else
				{
					world.blocks[nxt][y][x] = false;
				}
			}
		}
	}
	world.currBlocks = nxt;
}

void GameOfLife::onClick(SDL_Event* e)
{
	int xPos, yPos;
	int mask;
	if (e->type == SDL_MOUSEBUTTONDOWN) 
	{
		mask = SDL_GetMouseState(&xPos, &yPos);
		if (SDL_BUTTON(1)) {
			int x = xPos / world.unit;
			int y = yPos / world.unit;
			world.blocks[world.currBlocks][y][x] = !world.blocks[world.currBlocks][y][x];
		}
	}
}

void GameOfLife::onKeyEvent(SDL_Event* e)
{
	if (e->key.state == SDL_RELEASED)
	{
		switch (e->key.keysym.scancode)
		{
		case SDL_SCANCODE_Q:
			quit = true;
			break;
		case SDL_SCANCODE_S:
			simulation();
			break;
		case SDL_SCANCODE_R:
			random();
			break;
		case SDL_SCANCODE_C:
			start = true;
			break;
		default:
			break;
		}
	}
	
}


GameOfLife::GameOfLife() : App("Game of life"), world(40, 25, 20)
{

}

